;(function(validator) {
	if (typeof define == "function" && define.amd) {
		define(["jquery"], validator);
	} else {
		validator($);
	}
}(function($) {
	$.fn.validator = function(cmd) {
		switch (cmd) {
			case "bind": {
				validator.bind(this, arguments[1]);
				break;
			}
			case "register": {
				validator.register(arguments[1], arguments[2]);
				break;
			}
			case "get": {
				return validator.get(arguments[1]);
			}
			default: {
				break;
			}
		}
	}

	var Validator = function() {
		var jQuery = jQuery || $;
		var d = function(m, l) {
		}, k = function(m, l) {
		}, h = {
			trim : true,
			validOnChange : false,
			validOnKeyup:true,
			allowEmpty : true,
			async : true,
			errorClass : null,
			errorClassEMUI5:null,
			errorBoder:null,
			successFunction : null,
			errorFunction : null,
			reInputFunction:null
		};
		var a = {};
		var i = {};
		var j = function(q, t, m, n, s, l,temp) {
			jQuery.extend(l, m);
			if (n) {
				s = i[n];
				if (!s) {
					d(n + " rule is undefined!");
					return true;
				}
			}
			var o;
			if (n) {
				l.type = n;
			}
			if (s.length == 3) {
				o = s(q, t, l);
			} else {
				o = s(q, l);
			}
			if (!o) {
				if (l.errorFunction) {
					var p = function() {
						if (m.errorClass && t) {
							t.addClass(m.errorClass);
						}
						if(m.errorClassEMUI5 && t)
							{
							 m.errorBorder.addClass(m.errorClassEMUI5)
							}
						!temp&&l.errorFunction(t || q, l);
					};
					if (m.async) {
						setTimeout(p, 1);
					} else {
						p();
					}
				}
				return false;
			}
			return true;
		};
		var b = function(q, r, n, l,temp) {
			if (!n.type) {
				if (!j(q, r, n, null, n.rule, l,temp)) {
					return false;
				}
			} else {
				var o = n.type;
				if (typeof (n.type) == "string") {
					o = [ n.type ];
				}
				var p = {};
				for ( var m = 0; m < o.length; m++) {
					if (!p[o[m]]) {
						if (!j(q, r, n, o[m], null, l,temp)) {
							return false;
						}
						p[o[m]] = 1;
					}
				}
			}
			return true;
		};
		var e = function(n,temp) {
			var q = n.attr("validator");
			if (!q) {
				return true;
			}
			var m = a[q];
			var v;
			switch (n.get(0).tagName) {
			case "SELECT":
				v = n.val();
				break;
			default:
				v = n[0].value;
			}
			var s = {};
			var t = [];
			for ( var o = 0; o < m.length; o++) {
				var r = {};
				if (m[o].trim) {
					v = $.trim(v);
				}
				if (!b(v, n, m[o], r,temp)) {
					return false;
				}
				t.push(r);
			}
			for ( var o = 0; o < m.length; o++) {
				var u = m[o];
				if (u.successFunction) {
					var l = t[o];
					var p = function() {
						if (u.errorClass && n) {
							n.removeClass(u.errorClass);
						}
						u.successFunction(n || v, l);
					};
					if (u.async) {
						// setTimeout(p, 1);
						p();
					} else {
						p();
					}
				}
			}
			return true;
		};
		var validator = function(p, n,temp) {
			if (typeof (n) == "object") {
				var q = {};
				if (b(p, null, n, q) && n.successFunction) {
					if (n.async) {
						setTimeout(function() {
							n.successFunction(p, q);
						}, 1);
					} else {
						n.successFunction(p, q);
					}
				}
				return;
			}
			var l = p, o = n;
			var u = jQuery(l);
			var v = u.get(0).tagName;
			o = (typeof (o) == "boolean" ? o : true);
			switch (v) {
			case "SELECT":
			case "INPUT":
			case "TEXTAREA":
				return e(u);
			}
			var r = u
					.find("select[validator],input[validator],textarea[validator]");
			var t = true;
			for ( var m = 0; m < r.length; m++) {
				if (!e(jQuery(r[m]),temp)) {
					if (o) {
						return false;
					} else {
						t = false;
					}
				}
			}
			return t;
		};
		validator.register = function(m, l) {
			i[m] = l;
		};
		validator.get = function(l) {
			return i[l];
		};
		var c = 0;
		validator.bind = function(m, o) {
			var n = [];
			var r = jQuery(m);
			o = jQuery.extend({}, h, o);
			r.keyup(function(){
				o.reInputFunction&&o.reInputFunction();
			})
			if (o.validOnChange) {
				r.blur(function() {
					validator(this, true);
				});
			}
			if(o.validOnKeyup)
			{
				r.keyup(function(){
					$(this).removeClass(h.errorClass);
					o.errorBorder&&o.errorBorder.removeClass(o.errorClassEMUI5);
				})
			}	
			for ( var p = 0; p < r.length; p++) {
				var q = jQuery(r[p]);
				var l = q.attr("validator");
				if (!l) {
					l = "validator" + (++c) + (new Date()).getTime();
					q.attr("validator", l);
				}
				if (!a[l]) {
					a[l] = [];
				}
				a[l].push(o);
				n.push(l);
			}
			return n;
		};
		validator.defaults = h;
		$.extend(validator.defaults ,{
			errorClass : "cas_error",
			autoFocus : false,
			errorFunction:function(obj , options){
				var css = "cas_error",
					msg = options.msg[options.type] || options.msg["default"];
				switch(options.type){
					case "require":
						css = "cas_warn";
						break;
				}
				
				$(options.msg_ct).html(msg);
				if(options.autoFocus)obj.focus();
			
				window.setTimeout(function(){
			
				},2000);
			},
			successFunction:function(obj , options){
			}
		});
		var g = validator, f = function(m, l) {
			return !m;
		};
		g.register("regex", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}
			if (!l.regex) {
				k("regex", "need parameter of 'regex'!");
				return false;
			}
			return l.regex.test(m);
		});
		g.register("require", function(m, l) {
			l.allowEmpty = false;
			return !f(m);
		});
		g.register("email", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}
			var n = null;
			if (l.separater) {
				n = l.separater;
			}

			var c = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9\-]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/i;
			var d = new RegExp(c);
			var a;
			if (n) {
				a = m.split(n);
			} else {
				a = [ m ];
			}
			for ( var b = 0; b < a.length; b++) {
				if (a[b].match(d) == null) {
					return false;
				}
			}
			return true;
		});
		g.register("mobile", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}
			return /^[0-9]{5,15}$/.test(m) ? true : false;
		});
		g.register("password", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}

			var reg1 = /^(?=.{8,32})(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).*$/;
			var reg2 = /[^0-9a-zA-Z`~!@#$%^&*-_=+,.|\\/;:'"'()\[\]{}<>]+/;
			return (reg1.test(m) && !reg2.test(m)) ? true : false;
		});
		g.register("nickname", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}
			
			//return /^[a-zA-Z0-9_]*$/.test(m) ? true : false;  //不包含中文
			return /^([^\u4E00-\u9FA5])*$/.test(m) ? true : false;   //除去中文外所有
		});
		g.register("numeric", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}
			
			return /^\d+$/.test(m) ? true : false;
		});
		g.register("eq", function(o, l) {
			if (!l.compareTo) {
				k("eq", "need parameter of 'compareTo'!");
				return false;
			}
			var m = jQuery(l.compareTo).val();
			if (!l.format) {
				return o == m;
			}
			var n = g.get("date");
			if (!(n(o, l) && n(m, l))) {
				return false;
			}
			return o.parseDate(l.format).getTime() == m.parseDate(l.format)
					.getTime();
		});
		g.register("lt", function(p, m) {
			if (m.allowEmpty && f(p)) {
				return true;
			}
			if (!m.compareTo) {
				k("lt", "need parameter of 'compareTo'!");
				return false;
			}
			var n = jQuery(m.compareTo).val();
			if (!m.format) {
				m.negative = true;
				var l = g.get("float");
				if (!l(p, m)) {
					return false;
				}
				if (!l(n, m)) {
					return false;
				}
				p = parseFloat(p);
				n = parseFloat(n);
				return p < n;
			}
			var o = g.get("date");
			if (!(o(p, m) && o(n, m))) {
				return false;
			}
			return p.parseDate(m.format) < n.parseDate(m.format);
		});
		g.register("le", function(o, n) {
			var m = g.get("eq");
			var l = g.get("lt");
			return m(o, n) || l(o, n);
		});
		g.register("gt", function(p, m) {
			if (m.allowEmpty && f(p)) {
				return true;
			}
			if (!m.compareTo) {
				k("gt", "need parameter of 'compareTo'!");
				return false;
			}
			var n = jQuery(m.compareTo).val();
			if (!m.format) {
				m.negative = true;
				var l = g.get("float");
				if (!l(p, m)) {
					return false;
				}
				if (!l(n, m)) {
					return false;
				}
				p = parseFloat(p);
				n = parseFloat(n);
				return p > n;
			}
			var o = g.get("date");
			if (!(o(p, m) && o(n, m))) {
				return false;
			}
			return p.parseDate(m.format) > n.parseDate(m.format);
		});
		g.register("ge", function(o, n) {
			var l = g.get("eq");
			var m = g.get("gt");
			return l(o, n) || m(o, n);
		});
		g.register("length", function(n, m) {
			if (m.allowEmpty && f(n)) {
				return true;
			}
			if (!(m.min || m.max)) {
				k("length", "need parameter of 'min' or 'max'!");
				return false;
			}
			var l = n.len();
			if (m.min && l < m.min) {
				return false;
			}
			if (m.max && l > m.max) {
				return false;
			}
			return true;
		});
		g.register("strLength", function(n, m) {
			if (m.allowEmpty && f(n)) {
				return true;
			}
			if (!(m.min || m.max)) {
				k("length", "need parameter of 'min' or 'max'!");
				return false;
			}
			var l = n.length;
			if (m.min && l < m.min) {
				return false;
			}
			if (m.max && l > m.max) {
				return false;
			}
			return true;
		});	
		g.register("range", function(o, n) {
			if (n.allowEmpty && f(o)) {
				return true;
			}
			if (!(n.min || n.max)) {
				k("range", "need parameter of 'min' or 'max'!");
				return false;
			}
			n.negative = true;
			var m = g.get("float");
			if (!m(o, n)) {
				return false;
			}
			var l = parseFloat(o);
			if (n.min && l < n.min) {
				return false;
			}
			if (n.max && l > n.max) {
				return false;
			}
			return true;
		});
		g.register("chinese", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}
			l.regex = /^[\u4E00-\u9FA5]$/;
			return g.get("regex")(m, l);
		});
		g.register("int", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}
			if (l.negative) {
				l.regex = /^[-]?\d+$/;
			} else {
				l.regex = /^\d+$/;
			}
			return g.get("regex")(m, l);
		});
		g.register("float", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}
			if (l.negative) {
				l.regex = /^[-]?\d+(\.\d+)?$/;
			} else {
				l.regex = /^\d+(\.\d+)?$/;
			}
			return g.get("regex")(m, l);
		});
		g.register("date", function(q, n) {
			if (n.allowEmpty && f(q)) {
				return true;
			}
			if (!n.format) {
				d("date", "need parameter of 'format'!");
				return false;
			}
			var p = {
				"\\." : "\\.",
				"M+" : "(0[1-9]|[1-9]|1[0-2])",
				"d+" : "(0[1-9]|[1-9]|[12][0-9]|3[01])",
				"y+" : "(\\d{4})",
				"H+" : "([0-9]|[01][0-9]|2[0-3])",
				"m+" : "([0-9]|[0-5][0-9])",
				"s+" : "([0-9]|[0-5][0-9])",
				S : "(\\d+)"
			};
			var l = n.format;
			for ( var m in p) {
				if (new RegExp("(" + m + ")").test(n.format)) {
					l = l.replace(RegExp.$1, p[m]);
				}
			}
			n.regex = new RegExp("^" + l + "$");
			if (!g.get("regex")(q, n)) {
				return false;
			}
			return q == q.parseDate(n.format).format(n.format);
		});
		g.register(
			"url",
			function(m, l) {
				if (l.allowEmpty && f(m)) {
					return true;
				}
				if (m.startWith("http://")) {
					m = m.substring(7);
				} else {
					if (m.startWith("https://")) {
						m = m.substring(8);
					} else {
						if (l.requireProtocol) {
							return false;
						}
					}
				}
				if (!m) {
					return false;
				}
				l.regex = /^[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/;
				return g.get("regex")(m, l);
			}
		);

		g.register("idCard", function(m, l) {
			if (l.allowEmpty && f(m)) {
				return true;
			}
			
			var reg=/^[1-9]{1}[0-9]{14}$|^[1-9]{1}[0-9]{16}([0-9]|[xX])$/;
			return reg.test(m) ? true : false;
		});
		
		return validator;
	}

	window.validator = window.validator || Validator();
}));

String.prototype.len = function() {
	return this.replace(/[^\x00-\xff]/g, "aa").length;
};

